home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 2_3 / engrave.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-20  |  13.2 KB  |  575 lines

  1. /*    SCCS Id: @(#)engrave.c    2.3    88/02/11
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3.  
  4. #include    "hack.h"
  5.  
  6. extern char *nomovemsg;
  7. extern char nul[];
  8. extern struct obj zeroobj;
  9. #ifdef KAA
  10. extern char *xname();
  11. #endif
  12. struct engr {
  13.     struct engr *nxt_engr;
  14.     char *engr_txt;
  15.     xchar engr_x, engr_y;
  16.     unsigned engr_lth;    /* for save & restore; not length of text */
  17.     long engr_time;    /* moment engraving was (will be) finished */
  18.     xchar engr_type;
  19. #define    DUST    1
  20. #define    ENGRAVE    2
  21. #define    BURN    3
  22. #ifdef MARKER
  23. #define MARK    4
  24. #define POLY    5    /* temporary type - for polymorphing engraving */
  25. #else
  26. #define POLY    4    /* temporary type - for polymorphing engraving */
  27. #endif
  28. } *head_engr;
  29.  
  30. /* random engravings */
  31. #ifdef KAA
  32. char *random_engr[] =
  33. #else
  34. char random_engr[][30] =
  35. #endif
  36.              {"Elbereth", "ad ae?ar um",
  37. #ifdef NEWCLASS
  38.              "?la? ?as he??",
  39. #endif
  40.             /* more added by Eric Backus */
  41.             "?ilroy wa? h?re", "?ala??iel", "Aba?don H?pe...",
  42.             "Fo? a ?ood time c?ll 6?6-4311"};
  43. #ifdef NEWCLASS
  44. #define RAND_ENGRS    7
  45. #else
  46. #define RAND_ENGRS    6
  47. #endif
  48.  
  49. struct engr *
  50. engr_at(x,y) register xchar x,y; {
  51. register struct engr *ep = head_engr;
  52.     while(ep) {
  53.         if(x == ep->engr_x && y == ep->engr_y)
  54.             return(ep);
  55.         ep = ep->nxt_engr;
  56.     }
  57.     return((struct engr *) 0);
  58. }
  59.  
  60. sengr_at(s,x,y) register char *s; register xchar x,y; {
  61. register struct engr *ep = engr_at(x,y);
  62. register char *t;
  63. register int n;
  64.     if(ep && ep->engr_time <= moves) {
  65.         t = ep->engr_txt;
  66. /*
  67.         if(!strcmp(s,t)) return(1);
  68. */
  69.         n = strlen(s);
  70.         while(*t) {
  71.             if(!strncmp(s,t,n)) return(1);
  72.             t++;
  73.         }
  74.     }
  75.     return(0);
  76. }
  77.  
  78. u_wipe_engr(cnt)
  79. register int cnt;
  80. {
  81.     if(!u.uswallow && !Levitation)
  82.         wipe_engr_at(u.ux, u.uy, cnt);
  83. }
  84.  
  85. wipe_engr_at(x,y,cnt) register xchar x,y,cnt; {
  86. register struct engr *ep = engr_at(x,y);
  87. register int lth,pos;
  88. char ch;
  89.     if(ep){
  90.         if(ep->engr_type != BURN) {
  91.         if(ep->engr_type != DUST) {
  92.             cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1;
  93.         }
  94.         lth = strlen(ep->engr_txt);
  95.         if(lth && cnt > 0 ) {
  96.             while(cnt--) {
  97.                 pos = rn2(lth);
  98.                 if((ch = ep->engr_txt[pos]) == ' ')
  99.                     continue;
  100.                 ep->engr_txt[pos] = (ch != '?') ? '?' : ' ';
  101.             }
  102.         }
  103.         while(lth && ep->engr_txt[lth-1] == ' ')
  104.             ep->engr_txt[--lth] = 0;
  105.         while(ep->engr_txt[0] == ' ')
  106.             ep->engr_txt++;
  107.         if(!ep->engr_txt[0]) del_engr(ep);
  108.         }
  109.     }
  110. }
  111.  
  112. read_engr_at(x,y) register int x,y; {
  113. register struct engr *ep = engr_at(x,y);
  114. register int    canfeel;
  115.     if(ep && ep->engr_txt[0]) {
  116.         switch(ep->engr_type) {
  117.         case DUST:
  118.         if(!Blind) pline("Something is written here in the dust.");
  119.         canfeel = 0;
  120.         break;
  121.         case ENGRAVE:
  122.         pline("Something is engraved here on the floor.");
  123.         canfeel = 1;
  124.         break;
  125.         case BURN:
  126.         pline("Some text has been burned here in the floor.");
  127.         canfeel = 1;
  128.         break;
  129. #ifdef MARKER
  130.         case MARK:
  131.         if(!Blind) pline("There's some graffiti here on the floor.");
  132.         canfeel = 0;
  133.         break;
  134. #endif
  135.         default:
  136.         impossible("Something is written in a very strange way.");
  137.         canfeel = 1;
  138.         }
  139.         if (canfeel || !Blind)
  140.         pline("You %s: \"%s\".",
  141.               (Blind) ? "feel the words" : "read",  ep->engr_txt);
  142.     }
  143. }
  144.  
  145. make_engr_at(x,y,s)
  146. register int x,y;
  147. register char *s;
  148. {
  149.     register struct engr *ep;
  150.  
  151.     if(ep = engr_at(x,y))
  152.         del_engr(ep);
  153.     ep = (struct engr *)
  154.         alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1));
  155.     ep->nxt_engr = head_engr;
  156.     head_engr = ep;
  157.     ep->engr_x = x;
  158.     ep->engr_y = y;
  159.     ep->engr_txt = (char *)(ep + 1);
  160.     (void) strcpy(ep->engr_txt, s);
  161.     ep->engr_time = 0;
  162.     ep->engr_type = DUST;
  163.     ep->engr_lth = strlen(s) + 1;
  164. }
  165. /*
  166.  *    freehand - returns true if player has a free hand
  167.  */
  168. int
  169. freehand(){
  170.  
  171.     return(!uwep ||
  172.        !uwep->cursed ||
  173.        (uwep->otyp != TWO_HANDED_SWORD && (!uarms || !uarms->cursed)));
  174. /*    if ((uwep && uwep->otyp == TWO_HANDED_SWORD) ||
  175.         (uwep && uarms))
  176.         return(0);
  177.     else
  178.         return(1);*/
  179. }
  180.  
  181.  
  182.  
  183. doengrave(){
  184. register int len, tmp;
  185. register char *sp, *sptmp;
  186. register struct engr *ep, *oep = engr_at(u.ux,u.uy);
  187. char buf[BUFSZ];
  188. xchar type;
  189. int spct;        /* number of leading spaces */
  190. register struct obj *otmp;
  191.     multi = 0;
  192.  
  193.     if(u.uswallow) {
  194.         pline("You're joking. Hahaha!");    /* riv05!a3 */
  195.         return(0);
  196.     }
  197.  
  198.     /* one may write with finger, weapon or wand */
  199.     /* edited by GAN 10/20/86 so as not to change
  200.      * weapon wielded.
  201.      */
  202.     otmp = getobj("#-()/", "write with");
  203.     if(!otmp) return(0);
  204.  
  205. #ifdef FREEHAND /* There's no reason you should be able to write with a wand
  206.          * while both your hands are tied up.  Also, it's necessary to
  207.          * prevent engraving with "worn" objects other than weapons.
  208.          */
  209.     if (!freehand() && otmp != uwep) {
  210. #else
  211.     /* added by GAN 10/20/86 to require you to need a hand to
  212.        write with.
  213.      */
  214.     if(!(otmp->owornmask || otmp->olet == WAND_SYM) && !freehand())  {
  215. #endif
  216.         pline("You have no free hand to write with!");
  217.         return(0);
  218.     }
  219. #ifdef KAA
  220.     if (cantwield(u.usym)) {
  221.         pline("You can't even hold anything!");
  222.         return(0);
  223.     }
  224.     if(otmp != &zeroobj && index("][0`",otmp->olet)) {
  225.         pline("You can't engrave with such a large object!");
  226.         return(1);
  227.     }
  228. #endif
  229.  
  230.     if(Levitation && otmp->olet != WAND_SYM){        /* riv05!a3 */
  231.         pline("You can't reach the floor!");
  232.         return(0);
  233.     }
  234.  
  235.     if(otmp == &zeroobj) {
  236.         pline("You write in the dust with your fingers.");
  237.         type = DUST;
  238.     } else if(otmp->olet == WAND_SYM && zappable(otmp)) {
  239.         /* changed so any wand gets zapped out, but fire
  240.          * wands become known.
  241.          */
  242.         if((objects[otmp->otyp].bits & NODIR))  {
  243.             zapnodir(otmp);
  244.             type = DUST;
  245.         }  else  {
  246.             switch(otmp->otyp)  {
  247.             case WAN_LIGHTNING:
  248.                 if(!objects[otmp->otyp].oc_name_known) {
  249.                     pline("The %s is a wand of lightning!",
  250.                         xname(otmp));
  251.                     objects[otmp->otyp].oc_name_known = 1;
  252.                     more_experienced(0,10);
  253.                 }
  254.                 type = BURN;
  255.                 break;
  256.             case WAN_FIRE:
  257.                 if(!objects[otmp->otyp].oc_name_known) {
  258.                     pline("The %s is a wand of fire!",
  259.                        xname(otmp));
  260.                     objects[otmp->otyp].oc_name_known = 1;
  261.                     more_experienced(0,10);
  262.                 }
  263.                 type = BURN;
  264.                 break;
  265.             case WAN_DIGGING:
  266.                 if(!objects[otmp->otyp].oc_name_known) {
  267.                     pline("The %s is a wand of digging!",
  268.                        xname(otmp));
  269.                     objects[otmp->otyp].oc_name_known = 1;
  270.                     more_experienced(0,10);
  271.                 }
  272.                 type = ENGRAVE;
  273.                 break;
  274.             case WAN_POLYMORPH:
  275.                 if(oep)  {
  276.                     del_engr(oep);
  277.                     oep = 0;
  278.                     type = POLY;
  279.                 }  else
  280.                     type = DUST;
  281.                 break;
  282.             case WAN_COLD:
  283.                 type = DUST;
  284.                 if(!oep || (oep->engr_type != BURN))
  285.                     break;
  286.             case WAN_CANCELLATION:
  287.             case WAN_MAKE_INVISIBLE:
  288.                 if(!oep) {        /* Eric Backus */
  289.                     type = DUST;
  290.                     break;
  291.                 }
  292.                 del_engr(oep);
  293.                 pline("The engraving on the floor vanishes!");
  294.                 return(1);
  295.                 break;
  296.             case WAN_TELEPORTATION:
  297.                 if(!oep)
  298.                     type = DUST;
  299.                 else  {
  300.                     register tx,ty;
  301.  
  302.                     do  {
  303.                         tx = rn1(COLNO-3,2);
  304.                         ty = rn2(ROWNO);
  305.                     }  while(!goodpos(tx,ty));
  306.                     oep->engr_x = tx;
  307.                     oep->engr_y = ty;
  308.                     pline("The engraving on the floor vanishes!");
  309.                     return(1);
  310.                 }
  311.                 break;
  312.             default:
  313.                 type = DUST;
  314.             }
  315.         }
  316.         if(type == DUST)
  317.             pline("You write in the dust with %s.",
  318.                doname(otmp));
  319.     
  320.     } else {
  321.         if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD ||
  322.         otmp->otyp == CRYSKNIFE || otmp->otyp == KATANA ||
  323.         otmp->otyp == SCIMITAR || otmp->otyp == BROAD_SWORD ||
  324.         otmp->otyp == SHORT_SWORD ||
  325.         otmp->otyp == LONG_SWORD || otmp->otyp == AXE) {
  326.             type = ENGRAVE;
  327.             if((int)otmp->spe <= -3) {
  328.                 pline("Your %s too dull for engraving.",
  329.                     aobjnam(otmp, "are"));
  330.                 type = DUST;
  331.                 /* following messaged added 10/20/86 - GAN */
  332.                 pline("You write in the dust with %s.",
  333.                    doname(otmp));
  334.             }  else
  335.                 pline("You engrave with %s.", doname(otmp));
  336. #ifdef MARKER
  337.         } else if(otmp->otyp == MAGIC_MARKER)  {
  338.             if(otmp->spe <= 0)  {
  339.                 pline("Your marker is dried out.");
  340.                 pline("You write in the dust with the marker.");
  341.                 type = DUST;
  342.             }  else  {
  343.                 pline("You write with %s.", doname(otmp));
  344.                 type = MARK;
  345.             }
  346. #endif
  347.         }  else  {
  348.             pline("You write in the dust with %s.",
  349.                doname(otmp));
  350.             type = DUST;
  351.         }
  352.     }
  353.     
  354.     if(type != POLY && oep && oep->engr_type == DUST){
  355.           pline("You wipe out the message that was written here.");
  356.           del_engr(oep);
  357.           oep = 0;
  358.     }
  359.     if(type == DUST && oep){
  360.     pline("You cannot wipe out the message that is %s in the rock.",
  361.             (oep->engr_type == BURN) ? "burned" : (oep->engr_type == ENGRAVE)? "engraved" : "scribbled");
  362.           return(1);
  363.     }
  364.     if(type == POLY)  {
  365. #ifdef MARKER
  366.         type = rnd(4);
  367. #else
  368.         type = rnd(3);
  369. #endif
  370.         strcpy(buf,random_engr[rn2(RAND_ENGRS)]);
  371.         switch(type){
  372.         case DUST:
  373.             pline("\"%s\" is now written on the ground.",buf);
  374.             break;
  375.         case ENGRAVE:
  376.             pline("\"%s\" is now engraved in the rock.",buf);
  377.             break;
  378.         case BURN:
  379.             pline("\"%s\" is now burned in the rock.",buf);
  380.             break;
  381. #ifdef MARKER
  382.         case MARK:
  383.             pline("\"%s\" is now scribbled on the rock.",buf);
  384.             break;
  385. #endif
  386.         default:
  387.             impossible("\"%s\" is now written in a very strange way.",
  388.                buf);
  389.         }
  390.     }  else  {
  391.         pline("What do you want to %s on the floor here? ",
  392.           (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write");
  393.         getlin(buf);
  394.         clrlin();
  395.     }
  396.     spct = 0;
  397.     sp = buf;
  398.     while(*sp == ' ') spct++, sp++;
  399.     len = strlen(sp);
  400.     if(!len || *buf == '\033') {
  401.         /* changed by GAN 11/01/86 to not recharge wand */
  402.         return(1);
  403.     }
  404.     if(otmp->otyp == WAN_FIRE) {
  405.         if (!Blind) pline("Flames fly from the wand.");
  406.         else pline("You feel the wand heat up.");
  407.     } else if(otmp->otyp == WAN_LIGHTNING) {
  408.         if (!Blind) {
  409.             pline("Sparks fly from the wand.");
  410.             pline("You are blinded by the flashing!");
  411.             Blinded += rnd(50);
  412.             seeoff(0);
  413.         } else pline("You hear crackling!");
  414.     } else if(otmp->otyp == WAN_DIGGING) {
  415.         if (!Blind) pline("Gravel flies up from the floor.");
  416.         else pline("You hear drilling!");
  417.       }
  418.             /* kludge by stewr 870708 */
  419.     for (sptmp = sp, tmp=0; !(tmp == len); sptmp++,tmp++) {
  420.             if (((type == DUST) && !rn2(25))
  421.              || (Blind && !rn2(12))
  422.              || (Confusion && !rn2(3))) {
  423.                  *sptmp = '!' + rn2(93); /* ASCII-code only */
  424.                }
  425.           }
  426.  
  427.     switch(type) {
  428.     case DUST:
  429.     case BURN:
  430.         if(len > 15) {
  431.             multi = -(len/10);
  432.             nomovemsg = "You finished writing.";
  433.         }
  434.         break;
  435.     case ENGRAVE:
  436. #ifdef MARKER
  437.     case MARK:
  438.         {    int len2;
  439.         
  440.             if(type == ENGRAVE)
  441.                 len2 = (otmp->spe + 3) * 2 + 1;
  442.             else
  443.                 len2 = (otmp->spe) * 2;
  444.             nomovemsg = "You finished writing.";
  445.             if(type != MARK)
  446. #else
  447.         {    int len2 = (otmp->spe + 3) * 2 + 1;
  448. #endif
  449.             nomovemsg = "You finished engraving.";
  450.             if(otmp->olet != WAND_SYM)  {
  451.                 if(otmp->olet == WEAPON_SYM)
  452.                     pline("Your %s dull.",
  453.                            aobjnam(otmp, "get"));
  454.                 if(len2 < len) {
  455.                     len = len2;
  456.                     sp[len] = 0;
  457.                     if(type == ENGRAVE)  {
  458.                         otmp->spe = -3;
  459.                     }  else  {
  460.                         pline("Your marker dries out!");
  461.                         otmp->spe = 0;
  462.                     }
  463.                     /* next line added by GAN 10/20/86 */
  464.                     pline("You only write \"%s\".", sp);
  465.                     nomovemsg = "You cannot write more.";
  466.                 } else
  467.                     otmp->spe -= len/2;
  468. #ifdef MARKER
  469.                 if(type == MARK)
  470.                     multi = -(len/10);
  471.                 else
  472. #endif
  473.                     multi = -len;
  474.             }  else
  475.                 multi = -(len/10);
  476.         }
  477.         break;
  478.     }
  479.     if(oep) len += strlen(oep->engr_txt) + spct;
  480.     ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1));
  481.     ep->nxt_engr = head_engr;
  482.     head_engr = ep;
  483.     ep->engr_x = u.ux;
  484.     ep->engr_y = u.uy;
  485.     sp = (char *)(ep + 1);    /* (char *)ep + sizeof(struct engr) */
  486.     ep->engr_txt = sp;
  487.     if(oep) {
  488.         (void) strcpy(sp, oep->engr_txt);
  489.         (void) strcat(sp, buf);
  490.         del_engr(oep);
  491.     } else
  492.         (void) strcpy(sp, buf);
  493.     ep->engr_lth = len+1;
  494.     ep->engr_type = type;
  495.     ep->engr_time = moves-multi;
  496.  
  497.     /* kludge to protect pline against excessively long texts */
  498.     if(len > BUFSZ-20) sp[BUFSZ-20] = 0;
  499.     
  500.     /* cute messages for odd wands */
  501.     switch(otmp->otyp)  {
  502.     case WAN_SLOW_MONSTER:
  503.         pline("The bugs on the ground slow down!");
  504.         break;
  505.     case WAN_SPEED_MONSTER:
  506.         pline("The bugs on the ground speed up!");
  507.         break;
  508.     case WAN_MAGIC_MISSILE:
  509.         pline("The ground is riddled by bullet holes!");
  510.         break;
  511.     case WAN_SLEEP:
  512.     case WAN_DEATH:    /* can't tell sleep from death - Eric Backus */
  513.         pline("The bugs on the ground stop moving!");
  514.         break;
  515.     case WAN_COLD:
  516.         pline("A few ice cubes drop from your %s.",xname(otmp));
  517.         break;
  518.     case WAN_STRIKING:
  519.         pline("The %s unsuccessfully fights your attempt to write!",xname(otmp));
  520.     }
  521.  
  522.     return(1);
  523. }
  524.  
  525. save_engravings(fd) int fd; {
  526. register struct engr *ep = head_engr;
  527.     while(ep) {
  528.         if(!ep->engr_lth || !ep->engr_txt[0]){
  529.             ep = ep->nxt_engr;
  530.             continue;
  531.         }
  532.         bwrite(fd, (char *) & (ep->engr_lth), sizeof(ep->engr_lth));
  533.         bwrite(fd, (char *) ep, sizeof(struct engr) + ep->engr_lth);
  534.         ep = ep->nxt_engr;
  535.     }
  536.     bwrite(fd, (char *) nul, sizeof(unsigned));
  537. #ifdef DGK
  538.     if (!count_only)
  539. #endif
  540.         head_engr = 0;
  541. }
  542.  
  543. rest_engravings(fd) int fd; {
  544. register struct engr *ep;
  545. unsigned lth;
  546.     head_engr = 0;
  547.     while(1) {
  548.         mread(fd, (char *) <h, sizeof(unsigned));
  549.         if(lth == 0) return;
  550.         ep = (struct engr *) alloc(sizeof(struct engr) + lth);
  551.         mread(fd, (char *) ep, sizeof(struct engr) + lth);
  552.         ep->nxt_engr = head_engr;
  553.         ep->engr_txt = (char *) (ep + 1);    /* Andreas Bormann */
  554.         head_engr = ep;
  555.     }
  556. }
  557.  
  558. del_engr(ep) register struct engr *ep; {
  559. register struct engr *ept;
  560.     if(ep == head_engr)
  561.         head_engr = ep->nxt_engr;
  562.     else {
  563.         for(ept = head_engr; ept; ept = ept->nxt_engr) {
  564.             if(ept->nxt_engr == ep) {
  565.                 ept->nxt_engr = ep->nxt_engr;
  566.                 goto fnd;
  567.             }
  568.         }
  569.         impossible("Error in del_engr?");
  570.         return;
  571.     fnd:    ;
  572.     }
  573.     free((char *) ep);
  574. }
  575.